function MODEL=Setup_MODEL(PP,SS)


%% Setup Variables
%--------------------------------------------------------------------------
% Variable Declarification
%--------------------------------------------------------------------------
% State: Exogenous  (State_Ex)
ExState     =   struct('Eta_Z',DsgeVarClass('Eta_Z',0,'State_Ex','Lin'),...
                       'Eta_M',DsgeVarClass('Eta_M',0,'State_Ex','Lin') ...
                       );
% State: Endogenous (State_En)
EnState     =   struct('Dist',DsgeVarClass('Dist',SS.Dist,'State_En','Lin'), ...
                       'Lag_B',DsgeVarClass('Lag_B',SS.B,'State_En','Lin'), ...
                       'Lag_ir',DsgeVarClass('Lag_ir',SS.ir,'State_En','Lin') ...
                       );
% Control: NK (Control)
NKControl   =   struct('N',DsgeVarClass('N',SS.N,'Control','Log'), ...
                       'w',DsgeVarClass('w',SS.w,'Control','Log'), ...
                       'mc',DsgeVarClass('mc',SS.mc,'Control','Log'), ...
                       'PAC',DsgeVarClass('PAC',SS.PAC,'Control','Lin'), ...
                       'Profit',DsgeVarClass('Profit',SS.Profit,'Control','Lin'), ...
                       'Y',DsgeVarClass('Y',SS.Y,'Control','Log'), ...
                       'Pir',DsgeVarClass('Pir',SS.Pir,'Control','Lin'), ...
                       'ir',DsgeVarClass('ir',SS.ir,'Control','Lin'), ...
                       'T',DsgeVarClass('T',SS.T,'Control','Lin'), ...
                       'B',DsgeVarClass('B',SS.B,'Control','Lin'), ...
                       'TAU',DsgeVarClass('TAU',SS.TAU,'Control','Lin'), ...
                       'rr',DsgeVarClass('rr',SS.rr,'Control','Lin') ...
                       );
% Control: HH (Control)
HHControl   =   struct('ValFun',DsgeVarClass('ValFun',SS.ValFun,'Control','Lin'), ...
                       'C',DsgeVarClass('C',SS.C,'Control','Log'), ...
                       'L',DsgeVarClass('L',SS.L,'Control','Log'), ...
                       'AggStat',DsgeVarClass('AggStat',SS.AggStat,'Control','Log'));
% Auxiliary Variables: Aux
AuxVar      =   struct();
% Variable Collections: VAR
VAR         =   struct();
VAR_Cell    =   {ExState,EnState,NKControl,HHControl,AuxVar};
for ii=1:length(VAR_Cell)
    TempFields  =   fieldnames(VAR_Cell{ii});
    for jj=1:length(TempFields)
        TempVar     =   TempFields{jj};
        TempVarp    =   [TempVar,'p'];
        VAR.(TempVar) ...
                    =   VAR_Cell{ii}.(TempVar);
        VAR.(TempVarp) ...
                    =   VAR_Cell{ii}.(TempVar);
        VAR.(TempVarp).Name ...
                    =   [VAR.(TempVarp).Name,'p'];
    end
end

%--------------------------------------------------------------------------
% Variable Categories: State (XX), Control (YY) and Shocks (SH)
%--------------------------------------------------------------------------
% XX
XX              =   struct();
XX.VarList      =   cat(1,fieldnames(ExState),fieldnames(EnState));
XX.LocIdx       =   struct();
XX.VarNum       =   length(XX.VarList);
XX.Dim          =   0;
TempStartIdx    =   0;
for ii=1:XX.VarNum
    TempVar         =   XX.VarList{ii};
    TempDim         =   VAR.(TempVar).Dim;
    XX.Dim          =   XX.Dim+TempDim;
    XX.LocIdx.(TempVar) ...
                    =   TempStartIdx+(1:TempDim)';
    TempStartIdx    =   TempStartIdx+TempDim;
end
% YY
YY              =   struct();
YY.VarList      =   cat(1,fieldnames(HHControl),fieldnames(NKControl));
YY.LocIdx       =   struct();
YY.VarNum       =   length(YY.VarList);
YY.Dim          =   0;
TempStartIdx    =   0;
for ii=1:YY.VarNum
    TempVar         =   YY.VarList{ii};
    TempDim         =   VAR.(TempVar).Dim;
    YY.Dim          =   YY.Dim+TempDim;
    YY.LocIdx.(TempVar) ...
                    =   TempStartIdx+(1:TempDim)';
    TempStartIdx    =   TempStartIdx+TempDim;
end
% SH
SH              =   struct();
SH.VarList      =   fieldnames(ExState);
SH.LocIdx       =   struct();
SH.Dim          =   0;
SH.VarNum       =   length(SH.VarList);
TempStartIdx    =   0;
for ii=1:SH.VarNum
    TempVar         =   SH.VarList{ii};
    SH.VarList{ii}  =   ['Eps_',TempVar];
    TempDim         =   VAR.(TempVar).Dim;
    SH.Dim          =   SH.Dim+TempDim;
    SH.LocIdx.(SH.VarList{ii}) ...
                    =   TempStartIdx+(1:TempDim)';
    TempStartIdx    =   TempStartIdx+TempDim;
end

%--------------------------------------------------------------------------
% Duplicate the Variables Information in XXp, YYp
%--------------------------------------------------------------------------
% XXp
XXp             =   struct();
XXp.VarNum      =   XX.VarNum;
XXp.Dim         =   XX.Dim;
XXp.VarList     =   cell(XXp.VarNum,1);
for ii=1:XX.VarNum
    TempVar         =   XX.VarList{ii};
    TempVarp        =   [TempVar,'p'];
    XXp.VarList{ii} =   TempVarp;
    XXp.LocIdx.(TempVarp) ...
                    =   XX.LocIdx.(TempVar);
end
% YYp
YYp             =   struct();
YYp.VarNum      =   YY.VarNum;
YYp.Dim         =   YY.Dim;
YYp.VarList     =   cell(YYp.VarNum,1);
for ii=1:YY.VarNum
    TempVar         =   YY.VarList{ii};
    TempVarp        =   [TempVar,'p'];
    YYp.VarList{ii} =   TempVarp;
    YYp.LocIdx.(TempVarp) ...
                    =   YY.LocIdx.(TempVar);
end

VarBlock        =   struct('SH',SH,'XX',XX,'YY',YY,'XXp',XXp,'YYp',YYp);

%% Setup Equations
%--------------------------------------------------------------------------
% Variable Declarification (In and Out sides cannot include same variables)
%--------------------------------------------------------------------------
% HH Block
arg_List        =   {'In','Out'};
arg.In          =   {'Dist','ValFunp','Pir','T','Profit','TAU','ir','w'}';
arg.Out         =   {'Distp','ValFun','B','L','C','AggStat'}';

Equ             =   struct();
for ii=1:length(arg_List)
    IO              =   arg_List{ii};
    TempNum         =   length(arg.(IO));
    TempVarFlag     =   false(TempNum,1);
    Equ.Dim.(IO)    =   0;
    Equ.LocIdx.(IO) =   struct();
    TempStartIdx    =   0;
    for jj=1:TempNum
        TempVar         =   arg.(IO){jj};
        if ischar(TempVar)
            TempVarFlag(jj) =   1;
            Equ.Dim.(IO)    =   Equ.Dim.(IO)+VAR.(TempVar).Dim;
            Equ.LocIdx.(IO).(TempVar) ...
                            =   TempStartIdx+(1:VAR.(TempVar).Dim)';
            TempStartIdx    =   TempStartIdx+VAR.(TempVar).Dim;
        elseif isvector(TempVar)
            Equ.Dim.(IO)    =   Equ.Dim.(IO)+length(TempVar);
            TempStartIdx    =   TempStartIdx+length(TempVar);
        else
            error('Unknown input/output type');
        end
    end
    Equ.Var.(IO)    =   arg.(IO)(TempVarFlag);
    Equ.Num.(IO)    =   sum(TempVarFlag);
end

Equ_HH          =   Equ;
% NK Block
arg_List        =   {'In','Out'};
arg.In          =   {'Eta_Z','Eta_Zp','Eta_M','Eta_Mp','N','w','mc','Y',...
                     'Yp','Profit','PAC','L','C','Pir','Pirp','T',...
                     'TAU','B','Lag_B','Lag_Bp','ir','Lag_ir','Lag_irp','rr' ...
                     }';
arg.Out         =   {zeros(15,1)}';


Equ             =   struct();
for ii=1:length(arg_List)
    IO              =   arg_List{ii};
    TempNum         =   length(arg.(IO));
    TempVarFlag     =   false(TempNum,1);
    Equ.Dim.(IO)    =   0;
    Equ.LocIdx.(IO) =   struct();
    TempStartIdx    =   0;
    for jj=1:TempNum
        TempVar         =   arg.(IO){jj};
        if ischar(TempVar)
            TempVarFlag(jj) =   1;
            Equ.Dim.(IO)    =   Equ.Dim.(IO)+VAR.(TempVar).Dim;
            Equ.LocIdx.(IO).(TempVar) ...
                            =   TempStartIdx+(1:VAR.(TempVar).Dim)';
            TempStartIdx    =   TempStartIdx+VAR.(TempVar).Dim;
        elseif isvector(TempVar)
            Equ.Dim.(IO)    =   Equ.Dim.(IO)+length(TempVar);
            TempStartIdx    =   TempStartIdx+length(TempVar);
        else
            error('Unknown input/output type');
        end
        
        
    end
    Equ.Var.(IO)    =   arg.(IO)(TempVarFlag);
    Equ.Num.(IO)    =   sum(TempVarFlag);
end

Equ_NK          =   Equ;

%--------------------------------------------------------------------------
% Equation Collection
%--------------------------------------------------------------------------
EquBlock        =   struct('HH',Equ_HH,'NK',Equ_NK);

%% Setup Model
MODEL           =   struct('VAR',VAR,'VarBlock',VarBlock,'EquBlock',EquBlock);
%--------------------------------------------------------------------------
% Model Information
%--------------------------------------------------------------------------
% Variables
VarDim          =   VarBlock.XX.Dim+VarBlock.YY.Dim;
% Equations
EquList         =   fieldnames(EquBlock);
EquNum          =   length(EquList);
EquDim          =   0;
for ii=1:EquNum
    EquDim          =   EquDim+EquBlock.(EquList{ii}).Dim.Out;
end

if EquDim~=VarDim
    error(['Dimension Inconsistency: ', ...
           num2str(VarDim), ' Variables ',',with ',num2str(EquDim),' Equations']);
end

MODEL.Info      =   struct('Dim',EquDim,'EquList',{EquList});
